package com.saris.primego.common.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

public class JwtUtil {
    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {

        // 1. 清理密钥中的非法字符
        String cleanedKey = secretKey.replaceAll("[^A-Za-z0-9+/=]", "");
        // 2. base64编码
        byte[] base64key = Base64.getEncoder().encode(cleanedKey.getBytes(StandardCharsets.UTF_8));
        // 3. 将字符串密钥转换为安全的HMAC-SHA密钥
        SecretKey key = Keys.hmacShaKeyFor(base64key);


        return Jwts.builder()
                .claims(claims) // 自定义声明
                .issuedAt(new Date()) // 签发时间
                .expiration(new Date(System.currentTimeMillis() + ttlMillis)) // 过期时间
                .signWith(key) // 签名算法自动适配
                .compact();
    }

    /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     */
    public static Claims parseJWT(String secretKey, String token) {

        // 1. 清理密钥中的非法字符
        String cleanedKey = secretKey.replaceAll("[^A-Za-z0-9+/=]", "");
        // 2. base64编码
        byte[] base64key = Base64.getEncoder().encode(cleanedKey.getBytes(StandardCharsets.UTF_8));
        // 3. 将字符串密钥转换为安全的HMAC-SHA密钥
        SecretKey key = Keys.hmacShaKeyFor(base64key);


        try {
            // 得到DefaultJwtParser
            return Jwts.parser()
                    // 设置签名的秘钥
                    .verifyWith(key) // 验证签名
                    .build()
                    // 设置需要解析的jwt
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (JwtException e) {
            // Token 无效、过期或签名不匹配
            throw new RuntimeException("Invalid JWT: " + e.getMessage());
        }


    }

}
